/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.core.execution; import java.awt.AWTEvent; import java.awt.EventQueue; /** * * @author Ales Novak * @version 0.10 Mar 19, 1998 */ class TaskThreadGroup extends ThreadGroup { /** Class object for Thread */ private static final Class threadClass = Thread.class; /** lock for waitFor/wakeUpProcesses */ private Object TIMER = new Object(); /** true if RunClass thread entered waitFor - out of main method */ private boolean runClassThreadOut = false; /** true iff the ThreadGroup can be finalized - that is after all threads die */ private boolean finalizable; /** Is the process dead? The group can be marked as dead but still have running threads */ private boolean dead; TaskThreadGroup(ThreadGroup parent, String name) { super(parent, name); dead = false; } /** * @return true iff there is not any window there is not more than two threads * and first one if any must be waiting for next event in the queue (EventDispatchThread) and * the second must be instanceof ExecutionEngine$RunClass thread and must wait * external processes are never "dead" */ private boolean isProcessDead() { if (dead) { return true; } int count; // first System.out.println must be before sync block if (! finalizable) { return false; } synchronized (this) { count = activeCount(); /* Following lines patch bug in implementaion of java.lang.-Thread/ThreadGroup The bug - if new Thread(...) call is issued and the thread is not started. The thread is added as a member to its thread group - such threads are counted in calls activeCount() and enumerate(Thread[] ts, ...) although they do not live - e.g call destroy() to threadgroup always throws an exception. Solution is to start suspicious threads. I added try - catch block for already started threads. This is patch for some code used inside Swing - code like this " ... = new Thread().getThreadGroup();" see - javax.swing.SystemEventQueueUtilities$RunnableCanvas.maybeRegisterEventDispatchThread() Original error was that TaskThreadGroups that had not any threads at thread dump were not removed. !!! remove spagetti code if the bug is repaired in JDK. */ if (count > 1) { int active = 0; Thread[] threads = new Thread[count]; enumerate(threads); for (int i = threads.length; --i >= 0;) { if ((threads[i] != null) && (threads[i].isAlive()) ) { if (++active > 1) { return false; } } } count = active; } if (ExecutionEngine.hasWindows(this)) { return false; } if (count == 0) { return true; // no thread, no wins } // one thread remains - RunClass if (runClassThreadOut) { return true; } return false; } } /** blocks until this ThreadGroup die - isProcessDead = true */ void waitFor() { synchronized (TIMER) { try { while (! isProcessDead()) { if (Thread.currentThread() instanceof ExecutionEngine.RunClass) runClassThreadOut = true; try { TIMER.wait(1000); } catch (InterruptedException ex) { } } } finally { TIMER.notifyAll(); dead = true; } } } /** Marks this group as finalizable. */ void setFinalizable() { finalizable = true; } /** sets the group as dead */ void kill() { synchronized (TIMER) { if (! dead) { dead = true; TIMER.notifyAll(); try { TIMER.wait(3000); } catch (InterruptedException e) { } } } } } /* * Log * 10 Gandalf 1.9 11/9/99 Ales Novak improved killing of * tasks * 9 Gandalf 1.8 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 8 Gandalf 1.7 10/1/99 Ales Novak NullPointerException * 7 Gandalf 1.6 5/6/99 Ales Novak not changed * 6 Gandalf 1.5 3/31/99 Ales Novak * 5 Gandalf 1.4 3/25/99 Ales Novak * 4 Gandalf 1.3 3/25/99 Ales Novak * 3 Gandalf 1.2 3/24/99 Ales Novak * 2 Gandalf 1.1 1/8/99 Ales Novak * 1 Gandalf 1.0 1/5/99 Ian Formanek * $ */